跳轉到

pytest 學習指南(基礎篇)

基本操作

學習 pytest 可以大幅提升編寫單元測試的效率,並輕鬆整合至 CI/CD 工作流程中。建議從簡單的測試開始,逐步深入探索 pytest 的各種進階功能。

1. 安裝 pytest

在 Python 中使用 pytest 之前,必須先安裝它。可以通過 pip 來安裝:

pip install pytest

2. 撰寫一個簡單的測試案例

pytest 可以讓你輕鬆撰寫測試案例。假設有一個名為 math_func.py 的檔案,其中有一個簡單的函數:

# math_func.py
def add(x, y):
    return x + y

可以撰寫一個測試檔案,例如 test_math_func.py:

# test_math_func.py
from math_func import add

def test_add():
    assert add(1, 2) == 3
    assert add(0, 0) == 0
    assert add(-1, 1) == 0

3. 執行測試

在專案的根目錄下執行 pytest,其中 -v 表示詳細模式,顯示每個測試案例的結果。

pytest -v

pytest 會自動偵測以 test_ 開頭的檔案以及以 test_ 開頭的函數並執行它們。結果會詳細地顯示測試過程與結果。

成功PASS圖示

pytest 會自動解析錯誤訊息,使得測試失敗時提供更具可讀性的輸出。以下範例手動加入一個失敗的測試,pytest 會清楚告訴你預期值和實際結果的差異。

def test_add_fail():
    assert add(1, 2) == 0

接著在該目錄下執行 pytest -v 後即可看到這個測試項目有紅色的 fail。

失敗圖示

pytest 常用指令選項

選項 說明 用法範例
-v 詳細模式,顯示每個測試案例的結果 pytest -v
-s 顯示測試過程中的標準輸出,如 print() 內容 pytest -s
-k <expression> 僅運行符合條件的測試案例 pytest -k "test_function_name"
-m <mark> 僅運行特定標記的測試案例 pytest -m "slow"
-x 首次測試失敗時停止測試執行 pytest -x
--tb=short 縮短錯誤的 traceback 訊息,讓報告更簡潔 pytest --tb=short
--maxfail=<num> 遇到指定數量的測試失敗後停止執行測試 pytest --maxfail=2
--html=<file> 生成 HTML 格式的測試報告(需要 pytest-html 插件) pytest --html=report.html
--junitxml=<file> 生成 JUnit XML 格式的測試報告 pytest --junitxml=report.xml
--durations=<num> 列出運行時間最長的 <num> 個測試案例 pytest --durations=5
--cov=<module_or_path> 生成程式碼覆蓋率報告(需要 pytest-cov 插件) pytest --cov=my_module
--reuse-db 重新使用上次的資料庫測試環境(適用於測試資料庫環境) pytest --reuse-db

執行測試並生成 HTML 報告

我們可以將測試結果直接產生 report.html,只需要安裝 pytest-html 套件。

pip install pytest-html

接著執行測試並生成 HTML 報告,使用 --html 選項來指定報告的檔案名稱。此外,也可以同時搭配上方表格中的其他常用指令一起使用,以更靈活地控制測試流程。

pytest -v --html=report.html

這樣測試完成後,pytest 會在專案目錄下生成一個 report.html,裡面包含測試結果的詳細報告。

產生HTML報表

上述方法生成的報告,CSS 是獨立的,當分享報告時樣式可能會遺失。為了更好地分享並通過郵件展示報告,可以將 CSS 樣式合併到 HTML 中。

pytest --html=report.html --self-contained-html

使用 pytest 的進階功能

pytest 常用標記

標記 說明 用法範例
@pytest.mark.skip 跳過測試案例 @pytest.mark.skip(reason="Not implemented")
@pytest.mark.xfail 預期失敗的測試案例 @pytest.mark.xfail(raises=ZeroDivisionError)
@pytest.mark.parametrize 參數化測試,允許使用多組參數測試同一函數 @pytest.mark.parametrize("a,b", [(1, 2), (3, 4)])
@pytest.fixture 定義測試前置環境 @pytest.fixture

(1) pytest.fixture

fixture 可以用來設置測試前的準備步驟,例如初始化資料庫或建立物件:

import pytest

@pytest.fixture
def sample_data():
    return {"key": "value"}

def test_sample_data(sample_data):
    assert sample_data["key"] == "value"

(2) 測試多組輸入

可以使用 pytest.mark.parametrize 來測試多組輸入:

import pytest
from math_func import add

@pytest.mark.parametrize("a, b, expected", [(1, 2, 3), (0, 0, 0), (-1, 1, 0)])
def test_add_multi(a, b, expected):
    assert add(a, b) == expected